package com.xiaoxx.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxx.common.error.ErrorException;
import com.xiaoxx.common.result.RType;
import com.xiaoxx.enums.LoginEnum;
import com.xiaoxx.mapper.SysRoleMapper;
import com.xiaoxx.model.dto.sys.SysRoleDto;
import com.xiaoxx.model.dto.sys.SysRoleQuery;
import com.xiaoxx.model.entity.sys.*;
import com.xiaoxx.model.vo.sys.SysMenuVo;
import com.xiaoxx.model.vo.sys.SysRoleAllListVo;
import com.xiaoxx.model.vo.sys.SysRoleVo;
import com.xiaoxx.service.SysMenuService;
import com.xiaoxx.service.SysRoleMenuService;
import com.xiaoxx.service.SysRoleService;
import com.xiaoxx.service.SysRoleUserService;
import com.xiaoxx.utils.BeanDtoVoUtil;
import com.xiaoxx.utils.JwtUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * base--sys--角色管理 服务实现类
 * </p>
 *
 * @author HX
 * @since 2023-07-27
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Resource
    private SysRoleUserService sysRoleUserService;
    @Resource
    private SysRoleMenuService sysRoleMenuService;
    @Resource
    private SysMenuService sysMenuService;
    @Resource
    private HttpServletRequest request;

    @Override
    public IPage<SysRoleVo> listAdminRole(SysRoleQuery query) {
        Page<SysRole> sysRolePage = page(new Page<SysRole>(query.getCurrent(), query.getSize()), new LambdaQueryWrapper<SysRole>()
                .ne(SysRole::getCode, "SYS")
                .like(StringUtils.hasLength(query.getName()), SysRole::getName, query.getName())
                .orderByDesc(SysRole::getCreateTime));
        return BeanDtoVoUtil.pageVo(sysRolePage, SysRoleVo.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(SysRoleDto dto) {
        //新增角色
        SysRole adminRole = dto.convert(SysRole.class);
        save(adminRole);
        //新增菜单
        if (!dto.getMenuIds().isEmpty()) {
            //判断当前角色是否含有权限新增菜单
            String userId = JwtUtil.getJwtUser(request).getUserId();
            String roleId = getRoleIdByUserId(userId);
            if (!StringUtils.hasLength(roleId)) {
                throw new ErrorException(RType.NOT_AUTH);
            }
            //如果不是超级管理员
            if (!"1".equals(roleId)) {
                List<String> menuIds = sysRoleUserService.findCurrentMenuIds(userId);
                if (!menuIds.containsAll(dto.getMenuIds())) {
                    throw new ErrorException(RType.NOT_AUTH);
                }
            }
            List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
            for (String menuId : dto.getMenuIds()) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenu.setRoleId(adminRole.getId());
                sysRoleMenus.add(sysRoleMenu);
            }
            sysRoleMenuService.saveBatch(sysRoleMenus, 1024);
        }
        return adminRole.getId();
    }

    @Override
    public SysRoleVo findById(String id) {
        SysRoleVo sysRoleVo = getById(id).convert(SysRoleVo.class);
        List<SysMenu> list = sysMenuService.findByRoleId(id);
        if (!list.isEmpty()) {
            //遍历菜单
            List<SysMenuVo> vos = sysMenuService.traverseMenu(BeanDtoVoUtil.listVo(list, SysMenuVo.class));
            sysRoleVo.setMenuVos(vos);
        }
        return sysRoleVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean upd(SysRoleDto dto) {
        SysRole sysRole = dto.convert(SysRole.class);
        boolean b = this.updateById(sysRole);
        //删除角色菜单
        sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, sysRole.getId()));
        //新增菜单
        if (b) {
            if (!dto.getMenuIds().isEmpty()) {
                List<SysRoleMenu> adminRoleMenus = new ArrayList<>();
                for (String menuId : dto.getMenuIds()) {
                    SysRoleMenu adminRoleMenu = new SysRoleMenu();
                    adminRoleMenu.setMenuId(menuId);
                    adminRoleMenu.setRoleId(sysRole.getId());
                    adminRoleMenus.add(adminRoleMenu);
                }
                sysRoleMenuService.saveBatch(adminRoleMenus, 1024);
            }
        }
        return b;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(String id) {
        boolean b = this.removeById(id);
        //删除角色菜单
        sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, id));
        return b;
    }

    @Override
    public Boolean updDisable(String id, Integer disable) {
        return update(new LambdaUpdateWrapper<SysRole>()
                .set(SysRole::getDisable, disable)
                .eq(SysRole::getId, id));
    }

    @Override
    public List<SysRoleAllListVo> listAllRole(SysUser sysUser) {
        List<SysRole> list = new ArrayList<>();
        if (LoginEnum.SUPER_ADMIN.getUserName().equals(sysUser.getUsername()) && LoginEnum.SUPER_ADMIN.getFullName().equals(sysUser.getFullName())) {
            list = list(null);
        } else {
            list = list(new LambdaQueryWrapper<SysRole>()
                    .ne(SysRole::getId, "1"));
        }
        return BeanDtoVoUtil.listVo(list, SysRoleAllListVo.class);
    }

    @Override
    public SysRole getByCode(String code) {
        SysRole one = lambdaQuery()
                .eq(SysRole::getCode, code)
                .last("limit 1")
                .one();
        if (one == null) {
            return null;
        }
        return one;
    }

    @Override
    public SysRole getRoleNameByUserId(String userId) {
        SysRoleUser one = sysRoleUserService.getOne(new LambdaQueryWrapper<SysRoleUser>()
                .eq(SysRoleUser::getUserId, userId)
                .last("limit 1"));
        if (one != null) {
            SysRole sysRole = getById(one.getRoleId());
            if (sysRole != null) {
                return sysRole;
            }
        }
        return new SysRole();
    }


    private String getRoleIdByUserId(String userId) {
        SysRoleUser one = sysRoleUserService.lambdaQuery()
                .eq(SysRoleUser::getUserId, userId)
                .last("limit 1")
                .one();
        if (one == null) {
            return null;
        }
        return one.getRoleId();
    }
}
